package edu.kit.csl.cratylus.datatypes;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import edu.kit.csl.cratylus.extraction.WritingSystem;

/**
 * A sentence is represented as a list of words. A word could either consist of
 * letters or phonemes. Therefore, this class can be used for both, target and
 * source language sentences.
 */
public class Sentence implements Iterable<Word> {
	
	private List<Word> words = new ArrayList<Word>();
	
	/**
	 * Create a sentence instance from a blank separated string using a
	 * vocabulary.
	 * 
	 * @param senStr string representation of the sentence, which contains 
	 * 		the words separated by blanks 
	 * @param voc the vocabulary which should be updated with new words
	 */
	public Sentence(String senStr, Vocabulary voc) {
		parseString(senStr, voc);
	}

	/**
	 * Create a sentence instance from a blank separated string.
	 * 
	 * @param senStr string representation of the sentence, which contains 
	 * 		the words separated by blanks
	 */
	public Sentence(String senStr) {
		parseString(senStr, new Vocabulary());
	}
	
	/*
	 * Creates the words list by fetching a blank separated string.
	 * 
	 * @param senStr string representation of the sentence, which contains 
	 * 		the words separated by blanks 
	 * @param voc the vocabulary which should be updated with new words
	 */
	private void parseString(String senStr, Vocabulary voc) {
		String[] wordStrings = senStr.split(" ");
		for (String str : wordStrings) {
			if (str.length() > 0) {
				words.add(voc.get(str));
			}
		}
	}
	
	/**
	 * Create a sentence instance directly from a list of words.
	 * 
	 * @param words ordered list of words as they occur in the sentence
	 */
	public Sentence(List<Word> words) {
		this.words = words;
	}
	
	/**
	 * Get the length of the sentence in words.
	 * 
	 * @return the length of the sentence
	 */
	public int getLength() {
		return words.size();
	}
	
	/**
	 * Get the word in the specified position. This method is analogous to
	 * {@link List#get(int)} and also shares its further contracts.
	 * 
	 * @param index word position
	 * @return the word on the given position
	 */
	public Word get(int index) {
		return words.get(index);
	}
	
	/**
	 * Set the word at the specified position. This method is analogous to
	 * {@link List#set(int, Object)} and also shares its further contracts.
	 * 
	 * @param index word position
	 * @param Word the replacing word
	 */
	public void set(int index, Word word) {
		words.set(index, word);
	}

	@Override
	public Iterator<Word> iterator() {
		return words.iterator();
	}
	
	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		StringBuilder s = new StringBuilder();
		for (Word word : words) {
			if (!word.isNoise()) {
				s.append(" " + word.getContent());
			}
		}
		return s.toString().trim();
	}
	
	/**
	 * Same as {@link #toString()}, but using a writing system.
	 * 
	 * @param ws writing system for converting the word contents into their
	 * 			written representations
	 * @see #toString()
	 */
	public String toString(WritingSystem ws) {
		StringBuilder s = new StringBuilder();
		for (Word word : words) {
			if (!word.isNoise()) {
				s.append(" " + ws.convert(word));
			}
		}
		return s.toString().trim();
	}
}
